<?php defined('SYSPATH') or die('No direct script access.');

/**
 * Created by PhpStorm.
 * Author: ls
 * Time: 2020/06/04 9:44
 * Desc: uniapp优惠券处理
 */
class Model_Api_V2_Coupon
{

    /**
     * 判断会员优惠券的领取情况
     * @param $cid
     * @param $mid
     * @param null $total_num 总数量
     * @param null $max_num 最大数量
     * @return array int 1,可以领取 2:已经领完 3：已经领取，待使用 4:会员等级不满足
     */
    public static function check_receive_status($cid, $mid = null, $total_num = null, $max_num = null)
    {
        // 未设置会员等级直接不可领取
        $member_grades = DB::select('memeber_grades')
            ->from('coupon')
            ->where('id', '=', $cid)
            ->and_where('isopen', '=', 1)
            ->and_where('isdel', '=', 0)
            ->execute()
            ->get('memeber_grades');
        if (!$member_grades) {
            return array('status' => 2, 'surplus' => 0);
        }

        if (!$total_num || !$max_num) {
            $data      = DB::select('totalnumber', 'maxnumber')
                ->from('coupon')
                ->where('id', '=', $cid)
                ->execute()
                ->current();
            $total_num = $data['totalnumber'];
            $max_num   = $data['maxnumber'];
        }

        $member_coupon_total = DB::select('id')
            ->from('member_coupon')
            ->where('cid', '=', $cid)
            ->execute()
            ->count();

        if ($member_coupon_total < $total_num) {
            $status  = 1;
            $surplus = bcsub($max_num, $member_coupon_total, 0);//剩余数量
        } else {
            $status  = 2;
            $surplus = 0;
        }

        //会员信息
        if (!empty($mid)) {
            $member_total = DB::select('id')
                ->from('member_coupon')
                ->where('mid', '=', $mid)
                ->and_where('cid', '=', $cid)
                ->execute()
                ->count();
            if ($member_total >= $max_num) {
                $status  = 3;
                $surplus = $max_num;
            } else {
                $member_rank   = Model_Member::get_member_grade($mid);
                $member_grades = explode(',', $member_grades);
                if (!in_array($member_rank['id'], $member_grades)) {
                    $status = 4;
                }
            }
        }

        return array('status' => $status, 'surplus' => $surplus);
    }

    /**
     * 获取优惠券的适用类型
     * @param $cid
     * @param array $info ['typeid', 'modules']
     * @return mixed|string
     */
    public static function get_coupon_type($cid, $info)
    {
        $type_name = '';
        if ($info['typeid'] == 9999) {
            $type_names = DB::select(DB::expr('distinct sline_model.modulename, sline_model.id'))
                ->from('coupon_pro')
                ->join('model', 'left')
                ->on('coupon_pro.typeid', '=', DB::expr('sline_model.id'))
                ->where('coupon_pro.cid', '=', $cid)
                ->execute()
                ->as_array('model.id', 'model.modulename');
            if (!empty($type_names)) {
                $type_name = implode(',', $type_names);
            }
        } else {
            if ($info['modules']) {
                $modules = DB::select('modulename')
                    ->from('model')
                    ->where("id in ({$info['modules']})")
                    ->execute()
                    ->as_array('id', 'modulename');
                if (!empty($modules)) {
                    $type_name = implode(',', $modules);
                }
            }
        }
        return Common::cutstr_html($type_name, 18);
    }

    /**
     * 获取所有会员等级
     * @return array
     */
    public static function get_all_member_grade()
    {
        return DB::select('id', 'name')
            ->from('member_grade')
            ->execute()
            ->as_array('id', 'name');
    }

    /**
     * 获取优惠券会员等级
     * @param $member_grade_ids
     * @param array $all_grade
     * @return string[]
     */
    public static function get_member_grade($member_grade_ids, array $all_grade = array()): array
    {
        if (!$member_grade_ids) {
            return array('gradename_all' => '', 'gradename' => '');
        }

        if (empty($all_grade)) {
            $all_grade = self::get_all_member_grade();
        }

        $member_grade_ids = explode(',', $member_grade_ids);
        $member_grades    = DB::select('id', 'name')
            ->from('member_grade')
            ->where('id', 'in', $member_grade_ids)
            ->order_by('id')
            ->execute()
            ->as_array('id', 'name');
        if (count($member_grades) == count($all_grade)) {
            return array('gradename_all' => '', 'gradename' => '');
        }

        $grade_name_all = '';
        $grade_name     = '';
        if (!empty($member_grades)) {
            $member_grades  = array_values($member_grades);
            $grade_name     = $member_grades[0];
            $grade_name_all = implode('、', $member_grades);
        }

        return array('gradename_all' => $grade_name_all, 'gradename' => $grade_name);
    }

    /**
     * 判断是否即将过期 三天
     * @param $endtime
     * @return int 1 表示时间小于三天 2表示已经过期
     */
    public static function check_is_out($endtime)
    {
        $flag     = 0;
        $now_time = time();
        $dur      = $endtime - $now_time;
        if ($dur < 0) {
            $flag = 2;
        }
        if ($dur > 0 && $dur < 259200) {
            $flag = 1;
        }
        return $flag;
    }

    /**
     * 获取会员优惠券使用状态
     * @param array $coupon ['endtime', 'usenum', 'totalnum', 'isnever']
     * @return string
     */
    public static function get_use_status(array $coupon): string
    {
        $endTime    = $coupon['endtime'];
        $use_status = 'nouse';
        //未使用
        if (($coupon['usenum'] < $coupon['totalnum']) && ($endTime > time() || $coupon['isnever'] == 0)) {
            $use_status = 'use';
        }
        //已失效
        if ($endTime < time() && $coupon['isnever'] == 1) {
            $use_status = 'nouse';
        }
        //已使用
        if ($coupon['usenum'] == $coupon['totalnum']) {
            $use_status = 'used';
        }

        return $use_status;
    }

    /**
     * 格式化返回数据
     * @param $coupon
     * @return mixed
     */
    public static function format_return_data($coupon)
    {
        //是否即将要过期
        if ($coupon['isnever'] == 1) {
            $coupon['isout']     = Model_Api_V2_Coupon::check_is_out($coupon['endtime']);
            $coupon['starttime'] = date('Y-m-d', $coupon['starttime']);
            $coupon['endtime']   = date('Y-m-d', $coupon['endtime']);
        }

        //优惠券金额
        if ($coupon['type'] == 1) {
            $coupon['amount'] = number_format($coupon['amount'] * 10 / 100, 1);
        }

        //优惠券类型
        switch ($coupon['typeid']) {
            case 0:
                $coupon['typename'] = '无品类限制';
                break;
            case 1:
                $coupon['typename'] .= '产品可用';
                break;
            case 9999:
                $coupon['typename'] .= '部分产品可用';
                break;
        }

        // 抵扣类型
        if ($coupon['type'] == 1) {
            $coupon['amount'] .= '折';
        }

        // 限制字符串长度
        $coupon['gradename_all'] = Common::cutstr_html($coupon['gradename_all'] . '领取', 16);
        $coupon['typename']      = Common::cutstr_html($coupon['typename'], 12);

        return $coupon;
    }

    /**
     * 获取产品可使用优惠券
     * @param $type_id
     * @param $product_id
     * @param $mid
     * @param $start_time
     * @return array
     */
    public static function get_product_coupon($type_id, $product_id, $mid, $start_time = '')
    {
        $time = time();

        //获取该用户已经领取的所有未使用的优惠券
        $list = DB::select(DB::expr('sline_coupon.*,sline_member_coupon.id as roleid'))
            ->from('member_coupon')
            ->join('coupon', 'inner')
            ->on('member_coupon.cid', '=', DB::expr('sline_coupon.id'))
            ->where('member_coupon.mid', '=', $mid)
            ->and_where('member_coupon.totalnum', '>', DB::expr('sline_member_coupon.usenum'))
            ->and_where('member_coupon.cid', '>', 0)
            ->execute()
            ->as_array();

        $product_id = explode(',', $product_id);
        $coupon_list = array();
        foreach ($list as $item) {
            // 提前天数判断
            if ($item['antedate'] > 0 && $start_time > 0) {
                $start_time = strtotime($start_time);
                $flag_time  = strtotime(date('Y-m-d', time()));
                $flag       = ($start_time - $flag_time) / (24 * 60 * 60);
                if ($flag < $item['antedate']) {
                    continue;
                }
            }

            // 使用时间是否满足要求
            if ($item['isnever'] == 1) {
                if ($item['endtime'] < $time || $item['starttime'] > $time) {
                    continue;
                }
                $item['endtime']   = date('Y-m-d', $item['endtime']);
                $item['starttime'] = date('Y-m-d', $item['starttime']);
            }

            // 指定产品
            if ($item['typeid'] == 9999) {
                $check = DB::select('id')
                    ->from('coupon_pro')
                    ->where('cid', '=', $item['id'])
                    ->and_where('proid', 'in', $product_id)
                    ->and_where('typeid', '=', $type_id)
                    ->execute()
                    ->current();
                if (empty($check)) {
                    continue;
                }
            }

            // 指定产品类
            if ($item['typeid'] == 1) {
                if (!in_array($type_id, explode(',', $item['modules']))) {
                    continue;
                }
            }

            //金额比的时候计算金额
            if ($item['type'] == 1) {
                $item['amount'] = number_format($item['amount'] * 10 / 100, 1);
            }

            // 产品类型
            if ($item['typeid'] == 0) {
                $item['typename'] = '无品类限制';
            } else {
                $item['typename'] = Model_Api_V2_Coupon::get_coupon_type($item['id'], $item);
            }

            $coupon_list[] = $item;
        }

        return $coupon_list;
    }

    /**
     * @function 检查优惠券是否可以使用
     * @param int $roleid 会员领取优惠券之后的id
     * @param $totalprice
     * @param $typeid
     * @param $proid
     * @param int $starttime "Y-m-d"
     * @param $mid
     * @return array
     */
    public static function check_samount($roleid, $totalprice, $typeid, $proid, $starttime = 0, $mid)
    {
        $status = 0;
        //获取会员改产品可以使用的优惠券
        $out = self::get_pro_coupon($typeid, $proid, $starttime, $mid);
        if (empty($out)) {
            return array('status' => $status);
        }

        $roleids = array();
        foreach ($out as $o) {
            $roleids[] = $o['roleid'];
        }

        if (!in_array($roleid, $roleids)) {
            return array('status' => $status);
        }

        //检查该优惠券是否使用
        $conponid = DB::select('cid')
            ->from('member_coupon')
            ->where('id', '=', $roleid)
            ->and_where('usenum', '=', 0)
            ->execute()
            ->current();
        if (empty($conponid)) {
            return array('status' => $status);
        }

        $cid = $conponid['cid'];
        $couponinfo = DB::select('samount', 'amount', 'type', 'antedate', 'starttime')
            ->from('coupon')
            ->where("id", "=", $cid)
            ->execute()
            ->current();
        //金额是否满足
        if ($totalprice >= Currency_Tool::price($couponinfo['samount'])) {
            $status = 1;
            if ($couponinfo['type'] == 1) {
                $totalprice = floatval($totalprice * $couponinfo['amount'] / 100);
            } else {
                $totalprice = floatval($totalprice - Currency_Tool::price($couponinfo['amount']));
            }
        }
        if ($totalprice < 0) {
            $status = 0;
        }
        return array('status' => $status, 'totalprice' => $totalprice);
    }

    /**
     * @function 获取产品的优惠券信息
     * @param $typeid
     * @param $proid
     * @param int $starttime "Y-m-d"
     * @param $mid
     * @return array|bool
     */
    public static function get_pro_coupon($typeid, $proid, $starttime = 0, $mid)
    {

        $tpltime = $starttime;
        $time    = time();
        if (empty($mid)) {
            return false;
        }
        $out = array();
        //获取该用户已经领取的所有未使用的优惠券
        $sql        = "select * from sline_member_coupon WHERE mid=$mid and usenum=0 and cid>0";
        $list       = DB::query(1, $sql)->execute()->as_array();
        $couponlist = array();
        foreach ($list as $key => $l) {
            $w             = "id={$l['cid']}  ";
            $sql           = "select * from sline_coupon WHERE {$w}";
            $tpl           = DB::query(1, $sql)->execute()->current();
            $tpl['roleid'] = $l['id'];
            $couponlist[]  = $tpl;
        }
        foreach ($couponlist as $couponinfo) {
            //提前天数判断
            if ($couponinfo['antedate'] > 0 && $tpltime > 0) {
                $starttime = strtotime($tpltime);
                $flagtime  = strtotime(date('Y-m-d', time()));
                $flag      = ($starttime - $flagtime) / (24 * 60 * 60);
                if ($flag < $couponinfo['antedate']) {
                    continue;
                }
            }
            //使用时间是否满足要求
            if ($couponinfo['isnever'] == 1) {

                if ($couponinfo['endtime'] < $time || $couponinfo['starttime'] > $time) {
                    continue;
                }
                $couponinfo['endtime']   = date('Y-m-d', $couponinfo['endtime']);
                $couponinfo['starttime'] = date('Y-m-d', $couponinfo['starttime']);
            }
            //指定产品
            if ($couponinfo['typeid'] == 9999) {
                $check = DB::select('id')
                    ->from('coupon_pro')
                    ->where('cid', '=', $couponinfo['id'])
                    ->and_where('proid', '=', $proid)
                    ->and_where('typeid', '=', $typeid)
                    ->execute()
                    ->current();
                if (empty($check)) {
                    continue;
                }
                $couponinfo['typename'] = self::get_coupon_type($couponinfo['id'], $couponinfo);
            }
            //知道产品类
            if ($couponinfo['typeid'] == 1) {
                $couponinfo['typename'] = self::get_coupon_type($couponinfo['id'], $couponinfo);
                if (!in_array($typeid, explode(',', $couponinfo['modules']))) {
                    continue;
                }

            }
            //金额比的时候计算金额
            if ($couponinfo['type'] == 1) {
                $couponinfo['amount'] = number_format($couponinfo['amount'] * 10 / 100, 1);
            }
            $out[] = $couponinfo;
        }
        return $out;
    }

    /**
     * 获取可使用产品的导航
     * @param $type_ids
     * @return array
     */
    public static function get_use_product_nav($type_ids)
    {
        $out = array();
        foreach ($type_ids as $type_id) {
            $num = DB::select()
                ->from('search')
                ->where('typeid', '=', $type_id)
                ->and_where('ishidden', '=', 0)
                ->execute()
                ->count();

            if ($num > 0) {
                $module_name = DB::select('modulename')
                    ->from('model')
                    ->where("id", "=", $type_id)
                    ->execute()
                    ->get('modulename');
                $out[] = array('channelname' => $module_name, 'num' => $num, 'typeid' => $type_id);
            }
        }

        return $out;
    }

    /**
     * 获取指定的产品
     * @param $params
     * @return array
     */
    public static function get_use_product($params)
    {
        $page        = $params['page'] ?? 1;
        $pagesize    = $params['pagesize'] ?? 10;
        $type_id     = $params['type_id'] ?? '';
        $product_ids = $params['product_ids'] ?? '';

        $offset = St_Page::offset($page, $pagesize);

        $builder = DB::select()
            ->from('search')
            ->where('ishidden', '=', 0);
        if ($type_id) {
            $builder->and_where('typeid', '=', $params['type_id']);
        }

        if ($product_ids) {
            $builder->and_where('tid', 'in', $product_ids);
        }

        return $builder->order_by('typeid', 'ASC')
            ->limit($pagesize)
            ->offset($offset)
            ->execute()
            ->as_array();
    }

    /**
     * 获取允许使用优惠券的产品类型
     * @return array
     */
    public static function get_allow_product_model()
    {
        $not_allow_type = '14,12,4,6,7,11,10,101,109,107';
        $data           = DB::select('id')
            ->from('model')
            ->where("id not in ($not_allow_type)")
            ->and_where('isopen', '=', 1)
            ->and_where('is_couponable', '=', 1)
            ->execute()
            ->as_array('id');
        return array_unique(Arr::pluck($data, 'id'));
    }

    /**
     * 获取产品属性
     * @param $attr_id
     * @param $table
     * @return array
     */
    public static function get_product_attr($attr_id, $table)
    {
        $attr_list = array();
        // 如果产品有属性 传过去
        if ($attr_id) {
            $attr_table = $table . '_attr';
            $attr_list  = DB::select('attrname')
                ->from($attr_table)
                ->where(DB::expr("FIND_IN_SET(id,'" . $attr_id . "')"))
                ->execute()
                ->as_array();
        }
        return $attr_list;
    }

    /**
     * 订单使用优惠券
     * @param $coupon_id
     * @param $mid
     * @param $order
     * @return array|int[]
     * @throws Exception
     */
    public static function order_use_coupon_check($coupon_id, $mid, $order)
    {
        $cid = DB::select('cid')
            ->from('member_coupon')
            ->where('id', '=', $coupon_id)
            ->and_where('mid', '=', $mid)
            ->execute()
            ->current();
        if (!$cid) {
            throw new Exception('优惠券不存在');
        }
        // 获取总金额
        $total_price = Model_Coupon::get_order_totalprice($order);
        // 判断优惠券是否满足使用条件
        $check_res   = Model_Api_V2_Coupon::check_samount($coupon_id, $total_price, $order['typeid'], $order['productautoid'], 0, $mid);
        if ($check_res['status'] == 1) {
            $check_res['cid'] = $cid;
            $check_res['order_total_price'] = $total_price;
            return $check_res;
        } else {
            throw new Exception('优惠券不满足使用条件');
        }
    }
}